from typing import Optional, Tuple

import httpx

from core.formclass import SocialProfile
from lib.social.social import SocialProvider


class Google(SocialProvider):
    """社交登录
    doc:
    https://developers.google.com/identity/sign-in/web/sign-in
    它只使用类方法，不创建实例.
    """
    provider_name = "google"
    meta_data_url = "https://accounts.google.com/.well-known/openid-configuration"

    @classmethod
    def register(cls, oauth_instance, client_id, client_secret):
        oauth_instance.register(
            name=cls.provider_name,
            access_token_url="https://accounts.google.com/o/oauth2/token",
            access_token_params=None,
            authorize_url="https://accounts.google.com/o/oauth2/auth",
            authorize_params=None,
            api_base_url="https://www.googleapis.com",
            server_metadata_url=cls.meta_data_url,
            client_kwargs={
                'response_type': 'code',
                'token_endpoint_auth_method': 'client_secret_post',
                "scope": "email profile"
            },
        )

        oauth_instance.__getattr__(cls.provider_name).client_id = client_id
        oauth_instance.__getattr__(cls.provider_name).client_secret = client_secret

    @classmethod
    async def fetch_profile_data(cls, oauth_instance, auth_token) -> Optional[object]:
        """
        社交登录后获取个人资料信息.
        Args:
            oauth_instance (OAuth): OAuth 身份验证对象
            auth_token (Dict): 社会服务令牌
        Returns:
            SocialProfile
        Raises:
            HTTPException: HTTP status code 200 它发生在不
            ValueError: 它发生在社交登录失败时
        """
        response = await oauth_instance.__getattr__(cls.provider_name).get(
            'https://www.googleapis.com/oauth2/v3/userinfo', token=auth_token)
        # raise http status code 200 它发生在不
        response.raise_for_status()
        result = response.json()
        if (result.get("sub", None) is None and
                result.get("id", None) is None and
                result.get("email", None) is None):
            raise ValueError(result)

        return result

    @classmethod
    def convert_gnu_profile_data(cls, response) -> Tuple[str, SocialProfile]:
        """
        nouboard MemberSocialProfiles 用于 SocialProfile 转换为格式
        Args:
            response: 从社交提供者接收的个人资料信息
        """
        email = response.get("email", "")
        if response.get("sub", "") == "":
            identifier = response.get("id", "")
        else:
            identifier = response.get("sub", "")

        socialprofile = SocialProfile(
            mb_id=response.get("sub", ""),
            provider=cls.provider_name,
            identifier=identifier,
            profile_url=response.get("avatar", ""),
            photourl=response.get("avatar", ""),
            displayname=response.get("nickname", ""),
            disciption=""
        )

        return email, socialprofile

    @classmethod
    async def logout(cls, oauth_instance, auth_token):
        """
        社会服务令牌 revoke
        Args:
            oauth_instance (OAuth): OAuth 身份验证对象
            auth_token (Dict): 社会服务令牌
        """

        access_token = auth_token.get('access_token', None)
        async with httpx.AsyncClient() as client:
            await client.post('https://accounts.google.com/o/oauth2/revoke',
                              params={'token': access_token},
                              headers={'content-type': 'application/x-www-form-urlencoded'})
